package com.ygqh.baby.service.impl;

import com.aliyun.oss.*;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.ygqh.baby.ao.FileType;
import com.ygqh.baby.service.FileService;
import com.ygqh.baby.utils.CommonUtil;
import com.ygqh.baby.utils.DateConvertUtils;
import com.ygqh.baby.utils.HttpUtil;
import com.ygqh.baby.utils.ImageUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.Date;
import java.util.UUID;

@Service
public class FileServiceImpl implements FileService {

	private Logger logger = Logger.getLogger(this.getClass());
	@Value("${oss.aliyun.accessKeyId}")
	private String accessKeyId;
	@Value("${oss.aliyun.accessKeySecret}")
	private String accessKeySecret;
	@Value("${oss.aliyun.bucketName}")
	private String bucketName;
	@Value("${oss.aliyun.endpoint}")
	private String endpoint;
	@Value("${image.domain}")
	private String imageDomain;

	@Value("${image.upload.temp.url}")
	private String imageUploadTempUrl;

	@Value("${oss.aliyun.templatebucketName}")
	private String templatebucketName;

	private OSSClient ossClient = null;

	private OSSClient getOSSClient() {
		if (ossClient == null) {
			// 使用默认的OSS服务器地址创建OSSClient对象。
			return ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
		}
		return ossClient;
	}

	@Override
	public String upload2Oss(FileType fileType, MultipartFile file) {
		String originalFileName = file.getOriginalFilename();
		String postfix = originalFileName.split("\\.")[1];

		Assert.notNull(fileType);

		StringBuilder sbNewKey = new StringBuilder();
		sbNewKey.append(fileType.getName());
		sbNewKey.append("/");
		sbNewKey.append(DateConvertUtils.format(new Date(), "yyyyMMdd"));
		sbNewKey.append("/");
		sbNewKey.append(UUID.randomUUID().toString());
		sbNewKey.append("." + postfix);
		try {
			upload2Oss(sbNewKey.toString(), file.getBytes());
		} catch (IOException e) {
			e.printStackTrace();
		}

		return imageDomain + sbNewKey.toString();
	}

	@Override
	public String upload2Oss(FileType fileType, MultipartFile file, String fileName) {
		String originalFileName = file.getOriginalFilename();
		String postfix = originalFileName.split("\\.")[1];
		Assert.notNull(fileType);

		StringBuilder sbNewKey = new StringBuilder();
		sbNewKey.append(fileType.getName());
		sbNewKey.append("/");
		sbNewKey.append(fileName);
		sbNewKey.append("." + postfix);
		try {
			upload2Oss(sbNewKey.toString(), file.getBytes());
		} catch (IOException e) {
			e.printStackTrace();
		}

		return imageDomain + sbNewKey.toString();
	}

	@Override
	public String upload2Oss(final FileType fileType, final byte[] bytes) {
		Assert.notNull(fileType);
		Assert.isTrue(bytes.length > 0);

		StringBuilder sbNewKey = new StringBuilder();

		sbNewKey.append(fileType.name());
		sbNewKey.append("/");
		sbNewKey.append(DateConvertUtils.format(new Date(), "yyyyMMdd"));
		sbNewKey.append("/");
		sbNewKey.append(UUID.randomUUID().toString());

		upload2Oss(sbNewKey.toString(), bytes);

		return imageDomain + sbNewKey.toString();
	}

	@Override
	public void upload2Oss(final String key, byte[] bytes) {
		InputStream inputStream = null;
		try {
			inputStream = new ByteArrayInputStream(bytes);
			int contentLength = inputStream.available();

			ensureBucket(getOSSClient(), bucketName);

			ObjectMetadata objectMetadata = new ObjectMetadata();
			objectMetadata.setContentLength(contentLength);

			ossClient.putObject(bucketName, key, inputStream, objectMetadata);
			setBucketPublicReadable(getOSSClient(), bucketName);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			IOUtils.closeQuietly(inputStream);
		}
	}

	@Override
	public byte[] downloadFromOss(String key) {
		ensureBucket(getOSSClient(), bucketName);
		OSSObject object = ossClient.getObject(bucketName, key);
		InputStream inputStream = object.getObjectContent();
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		try {
			byte[] buffer = new byte[4096];
			int n = 0;
			while (-1 != (n = inputStream.read(buffer))) {
				output.write(buffer, 0, n);
			}
			output.close();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return output.toByteArray();
	}

	@Override
	public InputStream downloadIOFromOss(String key) {
		ensureBucket(getOSSClient(), bucketName);
		OSSObject object = ossClient.getObject(bucketName, key);
		InputStream inputStream = object.getObjectContent();

		return inputStream;
	}

	// 创建Bucket.
	private static void ensureBucket(OSSClient client, String bucketName) throws OSSException, ClientException {
		try {
			// 创建bucket
			Boolean exist = client.doesBucketExist(bucketName);
			if (!exist) {
				client.createBucket(bucketName);
			}
		} catch (ServiceException e) {
			if (!OSSErrorCode.BUCKET_ALREADY_EXISTS.equals(e.getErrorCode())) {
				// 如果Bucket已经存在，则忽略
				throw e;
			}
		}
	}

	// 把Bucket设置为所有人可读
	private static void setBucketPublicReadable(OSSClient client, String bucketName) throws OSSException, ClientException {
		// 创建bucket
		client.createBucket(bucketName);

		// 设置bucket的访问权限，public-read-write权限
		client.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
	}

	public String getUploadImageKey(FileType type, String originalFileName, String fileName) {
		String postfix = originalFileName.split("\\.")[1];
		StringBuilder sbNewKey = new StringBuilder();
		sbNewKey.append(type.getName());
		sbNewKey.append("/");
		String[] dateStrs = DateConvertUtils.format(new Date(), "yyyy-MM-dd").split("-");
		for (int i = 0; i < dateStrs.length; i++) {
			sbNewKey.append(dateStrs[i] + "/");
		}
		sbNewKey.append(fileName);
		sbNewKey.append("." + postfix);
		return sbNewKey.toString();
	}

	@Override
	public String uploadImage(MultipartFile uploadFile, FileType[] fileType, HttpServletRequest request, Boolean isFill) throws Exception {
		Assert.notEmpty(fileType);
		String originalFileName = System.currentTimeMillis() + "" + CommonUtil.generatorSmsValidateCode();
		int i = uploadFile.getOriginalFilename().lastIndexOf(".");
		String contentType = uploadFile.getContentType();
		System.out.println(contentType + "[][]" + uploadFile.getOriginalFilename());
		if (i == -1) {
			logger.info(uploadFile.getOriginalFilename() + "|" + uploadFile.getContentType());
		}
		String extName = ".jpg"; // uploadFile.getOriginalFilename().substring(i);
		for (FileType type : fileType) {
			String postfix = "-" + type.getWidth() + "*" + type.getHeight();
			String fileName = originalFileName + postfix;
			String key = this.getUploadImageKey(type, uploadFile.getOriginalFilename(), fileName);
			String imageTmpUrl = imageUploadTempUrl + uploadFile.getOriginalFilename().substring(0, uploadFile.getOriginalFilename().lastIndexOf(".")) + ".temp"
					+ extName;
			ImageUtils.scale2(uploadFile.getInputStream(), imageTmpUrl, type.getWidth(), type.getHeight(), isFill);
			this.upload2Oss(key, FileUtils.readFileToByteArray(new File(imageTmpUrl)));
		}
		String key = this.getUploadImageKey(fileType[0], uploadFile.getOriginalFilename(), originalFileName);
		this.upload2Oss(key, uploadFile.getBytes());
		return imageDomain + key;
	}

	@Override
	public String uploadAliaImage(String path, FileType fileType, Boolean isFill) throws Exception {

		String originalFileName = System.currentTimeMillis() + "" + CommonUtil.generatorSmsValidateCode();
		File file = new File(path);
		String key = this.getUploadImageKey(fileType, file.getName(), originalFileName);
		this.upload2Oss(key, HttpUtil.get(path).getBytes());
		return imageDomain + key;
	}

	@Override
	public String uploadImage(File uploadFile, FileType[] fileType, String extName, Boolean isFill, HttpServletRequest request) throws Exception {
		Assert.notEmpty(fileType);
		String originalFileName = System.currentTimeMillis() + "" + CommonUtil.generatorSmsValidateCode();
		for (FileType type : fileType) {
			String postfix = "-" + type.getWidth() + "*" + type.getHeight();
			String fileName = originalFileName + postfix;
			String key = this.getUploadImageKey(type, uploadFile.getName(), fileName);
			String imageTmpUrl = imageUploadTempUrl + uploadFile.getName().substring(0, uploadFile.getName().lastIndexOf(".")) + ".temp." + extName;
			if (type.getWidth() != null && type.getHeight() != null) {
				ImageUtils.scale2(new FileInputStream(uploadFile), imageTmpUrl, type.getWidth(), type.getHeight(), isFill);
				this.upload2Oss(key, FileUtils.readFileToByteArray(new File(imageTmpUrl)));
			}
		}
		String key = this.getUploadImageKey(fileType[0], uploadFile.getName(), originalFileName);
		this.upload2Oss(key, FileUtils.readFileToByteArray(uploadFile));
		return imageDomain + key;

	}

	@Override
	public String uploadImage(File uploadFile, FileType fileType, Boolean isFill) throws Exception {
		Assert.notNull(fileType);
		String originalFileName = System.currentTimeMillis() + "" + CommonUtil.generatorSmsValidateCode();
		String key = this.getUploadImageKey(fileType, uploadFile.getName(), originalFileName);
		this.upload2Oss(key, FileUtils.readFileToByteArray(uploadFile));
		return imageDomain + key;

	}

	// 上传专题预览html
	@Override
	public void uploadHtml2Oss(final String key, String filePath) {
		FileInputStream in = null;

		try {
			in = new FileInputStream(new File(filePath));

			int contentLength = in.available();

			ensureBucket(getOSSClient(), templatebucketName);

			ObjectMetadata objectMetadata = new ObjectMetadata();
			objectMetadata.setContentLength(contentLength);

			ossClient.putObject(templatebucketName, key, in, objectMetadata);

			setBucketPublicReadable(getOSSClient(), templatebucketName);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			IOUtils.closeQuietly(in);
		}
	}

	@Override
	public void uploadTemplateHtml2Target(String sourceHtml, String targetHtml) {
		try {
			ensureBucket(getOSSClient(), templatebucketName);
			ossClient.copyObject(templatebucketName, sourceHtml, templatebucketName, targetHtml);
			setBucketPublicReadable(getOSSClient(), templatebucketName);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	@Override
	public String uploadQrcode(String key,MultipartFile uploadFile, HttpServletRequest request) throws Exception {
			
			this.upload2Oss(key, uploadFile.getBytes());
		    return imageDomain + key;
	}

}
